package codeGeneration;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import freemarker.template.Template;
import lombok.Data;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 描述：代码生成器
 */

@Data
public class CodeGenerateUtils {
    private static final Log log = LogFactory.get();

    private Config config;

    public CodeGenerateUtils(Config config) {
        this.config = config;
    }

    public void generate() throws Exception {
        try {
            generateBaseEntity();
            generateBaseRepository();
            //生成Controller层文件
            generateControllerFile();
            generateEntity();
            generateRequest();
            generateQuery();
            generateRepository();
            generateService();
            generateServiceImpl();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private void generateEntity() throws Exception {
        final String suffix = ".java";
        File file = new File(config.getFilePath() + "/model/entity");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "Entity.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateControllerFile() throws Exception {
        final String suffix = "Controller.java";
        File file = new File(config.getFilePath() + "/controller");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "Controller.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateRequest() throws Exception {
        final String suffix = "Request.java";
        File file = new File(config.getFilePath() + "/model/request");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "Request.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateQuery() throws Exception {
        final String suffix = "Query.java";
        File file = new File(config.getFilePath() + "/model/request");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "Query.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateBaseEntity() throws Exception {
        final String suffix = "Entity.java";
        File file = new File(config.getBaseFilePath() + "/model");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "BaseEntity.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateBaseRepository() throws Exception {
        final String suffix = "EntityRepository.java";
        File file = new File(config.getBaseFilePath() + "/repository/jpa");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "BaseRepository.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateRepository() throws Exception {
        final String suffix = "Repository.java";
        File file = new File(config.getFilePath() + "/repository");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "Repository.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateService() throws Exception {
        final String suffix = "Service.java";
        File file = new File(config.getFilePath() + "/service");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "Service.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateServiceImpl() throws Exception {
        final String suffix = "ServiceImpl.java";
        File file = new File(config.getFilePath() + "/service");
        if (!file.exists()) {
            file.mkdirs();
        }
        final String path = file.getPath() + "/" + config.getEntityName() + suffix;
        final String templateName = "ServiceImpl.ftl";
        File mapperFile = new File(path);
        Map<String, Object> dataMap = new HashMap<>();
        generateFileByTemplate(templateName, mapperFile, dataMap);
    }

    private void generateFileByTemplate(final String templateName, File file, Map<String, Object> dataMap) throws Exception {
        Template template = FreeMarkerTemplateUtils.getTemplate(templateName);
        FileOutputStream fos = new FileOutputStream(file);
        dataMap.put("t", config);
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 10240);
        template.process(dataMap, out);
        log.info("{}", file.getPath());
    }
}